#include <wx/checkbox.h>
#include <wx/dcclient.h>
#include <wx/msgdlg.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>

#include <Klein/Application/ChangeNodeParameterClientData.h>
#include <Klein/Application/WorkspaceFrame.h>
#include <Klein/Application/SelectNodeClientData.h>
#include <Klein/Shader/GraphDatabase.h>

WorkspaceFrame::WorkspaceFrame(wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) :
	wxFrame(parent, id, title, pos, size, style)
{
	SetSizeHints(wxDefaultSize, wxDefaultSize);

	//
	mMenuBar = new wxMenuBar;
	SetMenuBar(mMenuBar);

	mFileMenu = new wxMenu;
	wxMenuItem* menuItemQuit = new wxMenuItem(mFileMenu, wxID_WORKSPACE_MENUITEM_QUIT, _("Quit"));
	mFileMenu->Append(menuItemQuit);

	mWindowMenu = new wxMenu;
	wxMenuItem* menuItemShowEditor = new wxMenuItem(mWindowMenu, wxID_WORKSPACE_MENUITEM_SHOWEDITOR, _("Show Editor"), wxEmptyString, wxITEM_CHECK);
	mWindowMenu->Append(menuItemShowEditor);
	menuItemShowEditor->Check(true);

	mHelpMenu = new wxMenu;
	wxMenuItem* menuItemAbout = new wxMenuItem(mHelpMenu, wxID_WORKSPACE_MENUITEM_ABOUT, _("About"));
	mHelpMenu->Append(menuItemAbout);
	
	mMenuBar->Append(mFileMenu, _("File"));
	mMenuBar->Append(mWindowMenu, _("Window"));
	mMenuBar->Append(mHelpMenu, _("Help"));

	//
	static int glArgs[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0};
	mCanvas = new GLCanvas(this, wxID_WORKSPACE_CANVAS, glArgs);

	wxBoxSizer* canvasSizer = new wxBoxSizer(wxVERTICAL);
	canvasSizer->Add(mCanvas, 1, wxEXPAND|wxALL, 5);

	SetSizer(canvasSizer);

	//
	mStatusBar = CreateStatusBar(1, wxST_SIZEGRIP, wxID_WORKSPACE_STATUSBAR);

	//
	mEditor = new EditorDialog(this);
	wxFlexGridSizer* flexGridSizer = new wxFlexGridSizer(2, 3, 0, 0);
	flexGridSizer->AddGrowableCol(0);
	flexGridSizer->AddGrowableCol(1);
	flexGridSizer->AddGrowableCol(2);
	flexGridSizer->SetFlexibleDirection(wxBOTH);
	flexGridSizer->SetNonFlexibleGrowMode(wxFLEX_GROWMODE_ALL);

	mEditor->SetSizer(flexGridSizer);
	mEditor->Show();

	//
	Layout();

	Centre(wxBOTH);
}

WorkspaceFrame::~WorkspaceFrame()
{
	delete mCanvas;
}

BEGIN_EVENT_TABLE(WorkspaceFrame, wxFrame)
	EVT_MENU(wxID_WORKSPACE_MENUITEM_SHOWEDITOR, WorkspaceFrame::OnEditorShow)
	EVT_COMMAND(wxID_WORKSPACE_CANVAS, wxEVT_COMMAND_BUTTON_CLICKED, WorkspaceFrame::OnEditorShowGraphNode)
END_EVENT_TABLE()

void WorkspaceFrame::OnEditorShow(wxCommandEvent& event)
{
	if (event.IsChecked())
	{
		mEditor->Show();
	}
	else
	{
		mEditor->Show(false);
	}
}

void WorkspaceFrame::OnEditorShowGraphNode(wxCommandEvent& event)
{
	SelectNodeClientData* selectNodeClientData = dynamic_cast<SelectNodeClientData*>(event.GetClientObject());
	assert(selectNodeClientData);

	int selectedNodeNumber = selectNodeClientData->GetSelectedNodeNumber();
	int activedNodeNumber = selectNodeClientData->GetActivedNodeNumber();
	if(selectedNodeNumber != activedNodeNumber)
	{
		bool destoryChildren = mEditor->DestroyChildren();
		assert(destoryChildren);

		wxFlexGridSizer* editorSizer = dynamic_cast<wxFlexGridSizer*>(mEditor->GetSizer());
		assert(editorSizer);

		//
		GraphDatabase& graphDatabase = GraphDatabase::GetReference();
		GraphRef activedGraph = graphDatabase.GetActivedGraph();

		activedGraph->ActiveNode(selectedNodeNumber);

		NodeRef node = activedGraph->GetNode(selectedNodeNumber);
		assert(node);

		//
		wxString editorTitle(_("Editor"));
		editorTitle.append(_(" - "));
		editorTitle.append(node->GetLabel().c_str());
		mEditor->SetTitle(editorTitle);

		//
		ParameterGroupRef parameterGroup = node->GetParameterGroup();
		const std::map<String, Parameter>& parameters = parameterGroup->GetParameters();

		editorSizer->SetRows(parameters.size());

		//
		for (std::map<String, Parameter>::const_iterator itr = parameters.begin(); itr != parameters.end(); ++ itr)
		{
			if (itr->second.GetIOType() == Parameter::IO_INPUT)
			{
				wxStaticText* label = new wxStaticText(mEditor, wxID_ANY, itr->first.c_str());
				editorSizer->Add(label, 0, wxALL|wxALIGN_RIGHT, 8);

				wxTextCtrl* text = new wxTextCtrl(mEditor, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
				text->Connect(wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(WorkspaceFrame::OnEditorTextCtrlEnter));
				text->SetClientObject(new ChangeNodeParameterClientData(node, itr->first.c_str()));
				text->AppendText(itr->second.GetRawValue().c_str());
				editorSizer->Add(text, 0, wxALL|wxALIGN_LEFT, 5);

				wxCheckBox* checkbox = new wxCheckBox(mEditor, wxID_ANY, _("Lock"));
				checkbox->SetValue(false);
				editorSizer->Add(checkbox, 0, wxALL|wxALIGN_LEFT, 8);
			}
		}

		mEditor->Layout();
	}
}

void WorkspaceFrame::OnEditorTextCtrlEnter(wxCommandEvent& event)
{
	ChangeNodeParameterClientData* changeNodeParameterClientData = dynamic_cast<ChangeNodeParameterClientData*>(event.GetClientObject());
	assert(changeNodeParameterClientData);

	NodeRef node = changeNodeParameterClientData->GetNode();
	const String& parameterName = changeNodeParameterClientData->GetParameterName();

	wxTextCtrl* textCtrl = dynamic_cast<wxTextCtrl*>(event.GetEventObject());
	assert(textCtrl);

	node->SetParameter(parameterName, textCtrl->GetValue().wx_str());
}
